/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 main.c
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Forrest Yu, 2005
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "stdio.h"
#include "const.h"
#include "protect.h"
#include "string.h"
#include "fs.h"
#include "proc.h"
#include "tty.h"
#include "console.h"
#include "global.h"
#include "proto.h"
#include "video.h"
#include "windows.h"

/*======================================================================*
 kernel_main
 *======================================================================*/
PUBLIC int kernel_main() {
	disp_str("-----\"kernel_main\" begins-----\n");

	NumOfWin = 0;
	struct task* p_task;
	struct proc* p_proc = proc_table;
	char* p_task_stack = task_stack + STACK_SIZE_TOTAL;
	u16 selector_ldt = SELECTOR_LDT_FIRST;
	int i, j, tempIndex;
	u8 privilege;
	u8 rpl;
	int eflags;
	int prio;
	for (i = 0; i < NR_TASKS + NR_PROCS; i++) {
		if (i < NR_TASKS) { /* 任务 */
			p_task = task_table + i;
			privilege = PRIVILEGE_TASK;
			rpl = RPL_TASK;
			eflags = 0x1202; /* IF=1, IOPL=1, bit 2 is always 1 */
			prio = 15;
		} else { /* 用户进程 */
			p_task = user_proc_table + (i - NR_TASKS);
			privilege = PRIVILEGE_USER;
			rpl = RPL_USER;
			eflags = 0x202; /* IF=1, bit 2 is always 1 */
			prio = 5;
		}

		strcpy(p_proc->name, p_task->name); /* name of the process */
		p_proc->pid = i; /* pid */

		p_proc->ldt_sel = selector_ldt;

		memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3],
				sizeof(struct descriptor));
		p_proc->ldts[0].attr1 = DA_C | privilege << 5;
		memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3],
				sizeof(struct descriptor));
		p_proc->ldts[1].attr1 = DA_DRW | privilege << 5;
		p_proc->regs.cs = (0 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl;
		p_proc->regs.ds = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl;
		p_proc->regs.es = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl;
		p_proc->regs.fs = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl;
		p_proc->regs.ss = (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | rpl;
		p_proc->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | rpl;

		p_proc->regs.eip = (u32) p_task->initial_eip;
		p_proc->regs.esp = (u32) p_task_stack;
		p_proc->regs.eflags = eflags;

		p_proc->nr_tty = 0;

		p_proc->p_flags = 0;
		p_proc->p_msg = 0;
		p_proc->p_recvfrom = NO_TASK;
		p_proc->p_sendto = NO_TASK;
		p_proc->has_int_msg = 0;
		p_proc->q_sending = 0;
		p_proc->next_sending = 0;

		for (j = 0; j < NR_FILES; j++)
			p_proc->filp[j] = 0;

		p_proc->ticks = p_proc->priority = prio;

		p_task_stack -= p_task->stacksize;
		p_proc++;
		p_task++;
		selector_ldt += 1 << 3;
	}

	proc_table[NR_TASKS + 0].nr_tty = 0;
	proc_table[NR_TASKS + 1].nr_tty = 1;
	proc_table[NR_TASKS + 2].nr_tty = 1;
	proc_table[NR_TASKS + 3].nr_tty = 1;

	k_reenter = 0;
	ticks = 0;

	p_proc_ready = proc_table;

//	vtest();
//	video_test();
	init_mouse();
	init_clock();
	//init_keyboard();
	//old_picture = ( unsigned short * )0x500;
	unsigned short color = vesa_compond_rgb(63, 63, 63);
	vesa_draw_point(200, 200, color);
	for (i = 0; i < 320; i++) {
		for (j = 0; j < 200; j++) {
			vesa_draw_point(i, j, 0);
		}
	}

	restart();

	while (1) {
	}
}

/*****************************************************************************
 *                                get_ticks
 *****************************************************************************/
PUBLIC int get_ticks() {
	MESSAGE msg;
	reset_msg(&msg);
	msg.type = GET_TICKS;
	send_recv(BOTH, TASK_SYS, &msg);
	return msg.RETVAL;
}

int tempLabel = 0;
/*======================================================================*
 TestA
 *======================================================================*/
void TestA() {
	int fd;
		int n,i=0,j;
		const char filename[] = "usr/root/hello.c";
		const char bufw[] = "abcde";
		const int rd_bytes = 1000;
		char bufr[rd_bytes];
		fd = open(filename,O_RDWR);
		read(fd,bufr,600);
		close(fd);
		printl("OH yeah! zhxxxxxxxxxxxxxxxxddha!\n%s\n",bufr);
		
		const char filename2[] = "/etc";
		char bufr2[500];
		n = list(filename2,bufr2,O_RDWR);
		printl("main function list number%d",n);
		while(i<n){
			
			printl("%s",bufr2+j);
			j+=strlen(bufr2+j)+1;
			i++;
		}
			
			


}

/*======================================================================*
 TestB
 *======================================================================*/
void TestB() {

	while (1) {

	}
}

/*======================================================================*
 TestC
 *======================================================================*/
void TestC() {

	while (1) {

	}
}

/*======================================================================*
 TestD
 *======================================================================*/
//void TestD() {
//	int i = 0x3000;
//	while (1) {
//	}
//	/*
//	 int MyWin, NotNullMsg;
//	 struct Message Consumption;
//
//	 int j=0;
//
//	 while(1){
//	 while(ToWait(MyWin)){};
//	 NotNullMsg = GetMessage(&SysMessages, &Consumption);
//	 //if (Consumption.LeftButtonDown) Resize(MyWin,WinRegister[MyWin].Height+1,WinRegister[MyWin].Width+1);
//	 milli_delay(200);
//	 }
//	 */
//}

///*======================================================================*
//                               TestA
// *======================================================================*/
//void TestA()
//{
//	int fd;
//	int n;
//	const char filename[] = "blah";
//	const char bufw[] = "abcde";
//	const int rd_bytes = 3;
//	char bufr[rd_bytes];
//
//	assert(rd_bytes <= strlen(bufw));
//
//	/* create */
//	fd = open(filename, O_CREAT | O_RDWR);
//	assert(fd != -1);
//	printf("File created. fd: %d\n", fd);
//
//	/* write */
//	n = write(fd, bufw, strlen(bufw));
//	assert(n == strlen(bufw));
//
//	/* close */
//	close(fd);
//
//	/* open */
//	fd = open(filename, O_RDWR);
//	assert(fd != -1);
//	printf("File opened. fd: %d\n", fd);
//
//	/* read */
//	n = read(fd, bufr, rd_bytes);
//	assert(n == rd_bytes);
//	bufr[n] = 0;
//	printf("%d bytes read: %s\n", n, bufr);
//
//	/* close */
//	close(fd);
//
//	spin("TestA");
//}
//
/*======================================================================*
                               TestB
 *======================================================================*/
//void TestB()
//{
//	while(1){
//		printf("B");
//		milli_delay(200);
//	}
//}

/*======================================================================*
                               TestB
 *======================================================================*/
//void TestC()
//{
//	/* assert(0); */
//	while(1){
//		printf("C");
//		milli_delay(200);
//	}
//}

/*****************************************************************************
 *                                panic
 *****************************************************************************/
PUBLIC void panic(const char *fmt, ...) {
	int i;
	char buf[256];

	/* 4 is the size of fmt in the stack */
	va_list arg = (va_list) ((char*) &fmt + 4);

	i = vsprintf(buf, fmt, arg);

	printl("%c !!panic!! %s", MAG_CH_PANIC, buf);

	/* should never arrive here */
	__asm__ __volatile__("ud2");
}
